﻿using CommonModel.Field;
using CommonModel.Model;
using GXRTBTC.PublicClassLibrary.Field;
using NewLife.Log;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
using static CommonModel.Model.DataTypeDll;

namespace GXRTBTC.PublicClassLibrary.Util
{
    /// <summary>
    /// xml配置解析
    /// </summary>
    class SchemaParseByCfg
    {

        public SchemaDocument parse(string xml)
        {
            SchemaDocument schemaDocument = new SchemaDocument();
            Dictionary<string, string> dynamicParaDictionary = new Dictionary<string, string>();

            System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
            XmlDocument doc = new XmlDocument();
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;//忽略文档里面的注释
            // 根据一级指标map, 顺序解析xml
            Dictionary<int, SchemaDictionary> schema = new();
            try
            {
                XmlReader reader = XmlReader.Create(xml, settings);
                doc.Load(reader);
                XmlNode rootEle = doc.SelectSingleNode("schema");//获得根节点
                XmlElement xe = (XmlElement)rootEle;//将节点转为元素
                string name = xe.GetAttribute("name");//得到节点元素的属性值
                schemaDocument.name = name;
                //schemaDocument.file_name = xml.Substring(xml.LastIndexOf("/") + 1).Substring(xml.LastIndexOf("\\") + 1);
                schemaDocument.file_name = Path.GetFileName(xml);
                string msgType = xe.GetAttribute("msgType");
                schemaDocument.msgType = msgType;
                string xmlType = xe.GetAttribute("xmlType");
                schemaDocument.xmlType = xmlType;
                string prefixCols = xe.GetAttribute("prefixCols");
                schemaDocument.prefixCols = prefixCols ?? "";
                XmlNodeList xn_child = rootEle.ChildNodes;//得到根节点的所有子节点

                Dictionary<int, XmlElement> fieldDictionary = new Dictionary<int, XmlElement>();
                // 生成所有一级指标map
                foreach (XmlNode xnc in xn_child)
                {
                    if (xnc is XmlElement)
                    {
                        XmlElement xec = (XmlElement)xnc;//将节点转换为元素
                        int id = int.Parse(xec.GetAttribute("index"));
                        //fieldDictionary.Add(id, xec);
                        DictAdd(fieldDictionary, id, xec);
                    }
                }

                // 对字段index进行排序, 以便顺序解析
                List<int> fieldOrderList = new List<int>(fieldDictionary.Keys);//把fieldDictionary的所有Key值放进list中
                fieldOrderList.Sort();


                for (int idx = 0; idx < fieldOrderList.ToArray().Length; idx++)
                {
                    XmlElement subElement = fieldDictionary[fieldOrderList[idx]];
                    // 递归解析element元素
                    if (null != subElement)
                    {
                        parseElement(schema, dynamicParaDictionary, idx, subElement, fieldOrderList[idx]);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(xml + " " + e.Message);
            }
            schemaDocument.fieldDictionary = schema;//将已读取XML文件后的XML字段规则放进schemaDocument
            schemaDocument.dynamicParaDictionary = dynamicParaDictionary;
            return schemaDocument;
        }

        private void parseElement(Dictionary<int, SchemaDictionary> schema, Dictionary<string, string> paraDictionary, int index, XmlElement element, int fieldIdx)
        {
            string fieldName = element.Name;//先获取到该节点的名字

            //以下是该节点的元素属性
            //int fieldIndex = Int32.Parse(element.GetAttribute("index"));
            int fieldIndex = fieldIdx;

            string strType = element.GetAttribute("type");
            DataType fieldType = DataTypeUtils.getType(strType.ToLower());

            string typeSize = element.GetAttribute("size");
            string deviceType = element.GetAttribute("deviceType");
            //string isAlarm = element.GetAttribute("isAlarm").ToLower();
            string loop = element.GetAttribute("loop");
            string code = element.GetAttribute("code").ToLower();
            string modIndex = element.GetAttribute("model_index");//命令码结构的索引，非必填
            string memo = element.GetAttribute("memo");
            string desc = element.GetAttribute("desc");
            //只有明确又save，且save为0时为不保存
            string save = element.GetAttribute("save");
            save = "0".Equals(save) ? "0" : "1";
            if (!"".Equals(desc))
            {
                memo = desc;
            }

            // 如果节点没有子节点, 解析字段
            if (element.ChildNodes.Count == 0)
            {
                SchemaDictionary field = new()
                {
                    // 必填
                    name = fieldName,
                    index = fieldIndex,
                    type = fieldType,
                    isSave = save,
                    memo = memo
                };

                // 非必填
                if (null != typeSize && !typeSize.Equals(""))
                {
                    field.size = int.Parse(typeSize);
                }
                else
                {
                    field.size = 1;
                }

                if (null != deviceType && !deviceType.Equals(""))
                {
                    field.deviceType = deviceType;
                }

                //if (null != isAlarm && isAlarm.Equals("true"))
                //{
                //    string alarmValue = element.GetAttribute("alarmValue");
                //    string alarmName = element.GetAttribute("alarmName");
                //    if (null != alarmValue && !alarmValue.Equals("") && null != alarmName && !alarmName.Equals(""))
                //    {
                //        field.isAlarm = true;
                //        field.alarmName = alarmName;
                //        field.alarmValue = alarmValue;
                //    }
                //}
                // 处理 loop 关联字段,即loop的值是某个变量，要取到这个变量名
                if (null != loop && !loop.Equals(""))
                {
                    // 正则表达式获取字段值
                    Regex regex = new Regex("\\$\\{(.*)\\}");
                    // 将字段记录到变量表
                    if (regex.IsMatch(loop))
                    {
                        loop = loop.Replace("${", "");
                        //string relateFieldName = loop.Replace("}", "");
                        loop = loop.Replace("}", "");
                        if (paraDictionary.ContainsKey(loop))
                        {
                            paraDictionary.Add(loop, loop);
                        }
                    }

                    field.loop = loop;
                }

                if (null != code && !code.Equals(""))
                {
                    field.code = code;
                }

                schema.Add(index, field);
            }
            else
            {
                // 如果节点有子节点, 解析字段
                Dictionary<int, XmlElement> fieldDictionary = new Dictionary<int, XmlElement>();

                SchemaDictionary schDictionary = new SchemaDictionary
                {
                    // 必填
                    name = fieldName,
                    index = fieldIndex,
                    type = fieldType,
                    isSave = save,
                    memo = memo
                };

                // 处理 loop 关联字段
                if (null != loop && !loop.Equals(""))
                {
                    // 正则表达式获取字段值
                    Regex regex = new Regex("\\$\\{(.*)\\}");
                    // 将字段记录到变量表
                    if (regex.IsMatch(loop))
                    {
                        loop = loop.Replace("${", "");
                        //string relateFieldName = loop.Replace("}", "");
                        loop = loop.Replace("}", "");
                        //paraDictionary.Add(loop, "");
                        if (paraDictionary.ContainsKey(loop))
                        {
                            paraDictionary.Add(loop, loop);
                        }
                    }

                    schDictionary.loop = loop;
                }

                // 非必填
                if (null != typeSize && !typeSize.Equals(""))
                {
                    schDictionary.size = int.Parse(typeSize);
                }
                else
                {
                    schDictionary.size = 1;
                }

                // 2020/11/16 增加命令码结构的索引  model_index, 非必填
                if (null != modIndex && !modIndex.Equals(""))
                {
                    schDictionary.index = int.Parse(modIndex);
                }

                if (null != deviceType && !deviceType.Equals(""))
                {
                    schDictionary.deviceType = deviceType;
                }

                //if (null != isAlarm && isAlarm.Equals("true"))
                //{
                //    string alarmValue = element.GetAttribute("alarmValue");
                //    string alarmName = element.GetAttribute("alarmName");
                //    if (null != alarmValue && !alarmValue.Equals("") && null != alarmName && !alarmName.Equals(""))
                //    {
                //        schDictionary.isAlarm = true;
                //        schDictionary.alarmName = alarmName;
                //        schDictionary.alarmValue = alarmValue;
                //    }
                //}
                if (null != loop)
                {
                    schDictionary.loop = loop;
                }

                if (null != code && !code.Equals(""))
                {
                    schDictionary.code = code;
                }

                // 生成所有子级指标map
                foreach (XmlNode xn_child in element)
                {
                    if (xn_child is XmlElement)
                    {
                        XmlElement subElement = (XmlElement)xn_child;
                        int id = int.Parse(subElement.GetAttribute("index"));
                        //fieldDictionary.Add(id, subElement);
                        DictAdd(fieldDictionary, id, subElement);
                    }
                }

                // 对字段index进行排序, 以便顺序解析
                List<int> fieldOrderList = new List<int>(fieldDictionary.Keys);
                fieldOrderList.Sort();
                // 根据一级指标map, 顺序解析xml

                Dictionary<int, SchemaDictionary> subSchema = new Dictionary<int, SchemaDictionary>();

                for (int idx = 0; idx < fieldOrderList.ToArray().Length; idx++)
                {
                    XmlElement subElement = fieldDictionary[fieldOrderList[idx]];
                    // 递归解析element元素
                    if (null != subElement)
                    {
                        parseElement(subSchema, paraDictionary, idx, subElement, fieldOrderList[idx]);
                    }
                }

                schDictionary.fieldDictionary = subSchema;
                schDictionary.isNode = true;
                schema.Add(index, schDictionary);
            }
        }

        private int DictAdd(Dictionary<int, XmlElement> dict, int key, XmlElement subElement)
        {
            while (dict.ContainsKey(key))
            {
                key++;
            }
            dict.Add(key, subElement);
            return key;
        }
    }
}
